<!DOCTYPE html>
<html>
  <head>
    <title>
      offlineaudiocontext-suspend-resume-eventhandler.html
    </title>
    <script src="../../resources/testharness.js"></script>
    <script src="../../resources/testharnessreport.js"></script>
    <script src="../resources/audit-util.js"></script>
    <script src="../resources/audit.js"></script>
  </head>
  <body>
    <script id="layout-test-code">
      let audit = Audit.createTaskRunner();

      let context;
      let renderQuantum = 128;

      // The sample rate is multiple of the rendering quantum, so suspension
      // times in the test will fall on the render quantum boundary. Although
      // this is not necessary, it is easier to understand the test.
      let sampleRate = renderQuantum * 100;

      let renderDuration = 2;
      let scheduledSuspendTime = 0;

      // With the sample rate setting above, this ensures suspension time fall
      // in to the render quantum boundary.
      let suspendInterval = 0.25;

      audit.define(
          {
            label: 'test',
            description: 'Test event handler from resume() and suspend()'
          },
          (task, should) => {
            context = new OfflineAudioContext(
                1, sampleRate * renderDuration, sampleRate);

            context.onstatechange = function() {
              if (context.state === 'suspended' &&
                  context.currentTime === scheduledSuspendTime) {
                should(
                    context.state === 'suspended' &&
                        context.currentTime === scheduledSuspendTime,
                    'onstatechange event handler: context is suspended at ' +
                        scheduledSuspendTime + ' second(s)')
                    .beTrue();
                scheduledSuspendTime = context.currentTime + suspendInterval;

                // Scheduling a suspend before the render duration should pass.
                if (scheduledSuspendTime < renderDuration) {
                  should(
                      () => context.suspend(scheduledSuspendTime),
                      'Scheduling a new suspend at ' + scheduledSuspendTime +
                          ' second(s)')
                      .notThrow();
                  ;
                }

                // Scheduling a suspend exactly at the render duration should be
                // rejected.
                if (scheduledSuspendTime === renderDuration) {
                  should(
                      context.suspend(scheduledSuspendTime),
                      'Scheduling at ' + renderDuration + ' seconds')
                      .beRejected();
                }

                context.resume();
              }
            };

            // This test is for verifying all the event handlers on OAC and that
            // is why 'oncomplete' is used here.
            context.oncomplete = function() {
              should(context.state, 'oncomplete event handler: context.state')
                  .beEqualTo('closed');
              task.done();
            };

            // Schedule the first suspension.
            should(
                () => context.suspend(scheduledSuspendTime),
                'A new suspend has been scheduled at ' + scheduledSuspendTime +
                    ' second(s)')
                .notThrow();
            ;

            context.startRendering();
          });

      audit.run();
    </script>
  </body>
</html>
